import { has, isArray, isPlainObject } from 'lodash-es';
import DeviceManager from './index';

/**
 * Types
 */
import type { DevicesType, RequestType, ResponseType } from '../typings';

declare const global: any;

declare const parentPort: any;

/**
 * Events
 * 前端界面下发：命令处理
 */
const requestCommand: (payload: Partial<RequestType>) => Promise<ResponseType> = (payload) => {
    return new Promise((resolve, reject) => {
        // 请求参数
        const request: RequestType = {
            ...(payload as RequestType),
            jsonrpc: '1.0',
            params: {
                content: isPlainObject(payload.params) ? payload.params : { value: payload.params },
            },
            type: 'rpc',
            callback: (res) => {
                if (res.code !== 200) {
                    return reject({
                        code: res.code ?? 50000,
                        message: res.message || '系统错误',
                    });
                }

                let data = res.data ?? res.result;

                // 返回结果有且只有 value
                if (has(data, 'value') && Object.keys(data).length === 1) {
                    data = data.value;
                }

                resolve({
                    code: 200,
                    data,
                    message: 'success',
                });
            },
        };

        // 命令调用：冒泡SDK运行环境
        window?.JeeWeb?.command(request, request.callback);

        // 命令调用超时
        setTimeout(
            () => {
                request.callback({
                    code: 50002,
                    message: '命令超时',
                });
            },
            // 如果默认一些长时间的设备，可以给下发的那里配置一下timeout设置属性
            /**自动生成部分json结构体
          "getLiveVideo": {
            "method": "getLiveVideo",
            "methodId": "UiWTUhTz",
            "type": "Number",
            "value": 5000,
            "timeout": 1800
            },
             *
             */
            (payload?.timeout || 10) * 1000,
        );
    });
};

/**
 * nodejs层命令处理：后台运行服务体系：cmd
 * @param payload
 * @returns
 */
const requestMessage: (payload: Partial<RequestType>) => any = (payload) => {
    return new Promise((resolve, reject) => {
        const id = window?.JeeWeb?.utils?.uuid();

        // 请求参数
        const request = {
            id,
            time: Date.now(),
            type: 'method',
            appId: global.appId,
            appType: global.appType,
            from: payload.to,
            methodInfo: {
                ...payload,
                params: isPlainObject(payload.params) ? payload.params : { value: payload.params },
            },
        };

        // 消息缓存：nodejs使用，promiseCaches在nodejs中已经全局声明，
        // 缓存消息内容，全局缓存，之前的局部。

        promiseCaches[id] = {
            resolve,
            reject,
        };

        // 给后台运行小应用命令调用
        parentPort?.postMessage(request);
    });
};

/**
 * 命令交互
 *
 * @see http://wiki.devjeejio.com/pages/viewpage.action?pageId=4096443
 */
export const command: (params: Partial<RequestType>) => Promise<ResponseType | ResponseType[]> = (params) => {
    // 判断是不是nodejs平台：requestMessage，否则使用requestCommand
    const request = window?.JeeWeb?.OS === 0x0b ? requestMessage : requestCommand;

    /**
     * Params
     */
    const { to, ...payload } = params;
    // console.log(JSON.stringify(payload), '----------payload');
    // console.log(JSON.stringify(to), '----------------to');
    // 1.单一设备：对象
    if (isPlainObject(to)) {
        return request({
            ...payload,
            to: (to as DevicesType).id,
        });
    }

    // 2.群组设备
    if (isArray(to)) {
        const promiseAll: Promise<ResponseType>[] = [];

        to.forEach((device) => {
            promiseAll.push(
                request({
                    ...payload,
                    to: (device as DevicesType).id,
                }),
            );
        });
        // allSettled必须全部执行完成后，才会执行。all是全量或竞态
        return Promise.allSettled(promiseAll).then((res) => {
            return res.map((item) => {
                if (item.status === 'fulfilled') {
                    // 成功：status和value
                    return item.value;
                }
                // 失败的结构：status和reason。
                return item.reason;
            });
        });
    }

    // 3.如果undefined的情况
    return Promise.reject({
        code: 50003,
        message: '设备未绑定',
    });
};
